package pl.edu.pw.MidEmu.Samples.MidasChat.Logic;

import java.awt.Point;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.Hashtable;

import javax.swing.JTextPane;
import javax.swing.JViewport;
import javax.swing.text.BadLocationException;

import midas.mw.cam.interfaces.Cam;
import midas.mw.cam.interfaces.CamConnection;
import midas.mw.ckb.interfaces.ABoxException;
import midas.mw.ckb.interfaces.Ckb;
import midas.mw.ckb.interfaces.DomainClass;
import midas.mw.ckb.interfaces.DomainInstance;
import midas.mw.ckb.interfaces.DomainProperty;
import midas.mw.interfaces.Mw;
import pl.edu.pw.MidEmu.Integration.MidEmuApplication;

/**
 * Helper class used by MIDAS chat application to receive messages from Middleware
 * @author mateusz
 *
 */
public class Receive extends Thread
{
	private Cam cam;
	private Ckb ckb;
	private String className;
	private CamConnection connection;
	private String instanceName;
	private Mw midas;
	private JTextPane pane;
	boolean runCondition = true;

	/**
	 * Default constructor for receive class
	 * @param className Context class name
	 * @param instanceName MIDAS instance identifier
	 * @param middlewareInterface MIDAS interface
	 * @param tbxRecievedText Panel for received messages
	 */
	public Receive(String className, String instanceName, Mw middlewareInterface, JTextPane tbxRecievedText)
	{
		this.midas = middlewareInterface;
		this.className = className;
		this.instanceName = "NODE_" + instanceName;
		this.pane = tbxRecievedText;
		cam = (Cam) midas.getRunningComponent("CAM");
		ckb = (Ckb) midas.getRunningComponent("CKB");
	}

	/**
	 * Displays and formats message on application's message panel
	 * @param msg
	 */
	public void receive(byte[] msg)
	{

		try
		{
			String text = new String(msg);
			if (text.length() > 0)
			{
				String message = new String(msg);
				String date = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT).format(Calendar.getInstance().getTime());
				pane.getDocument().insertString(pane.getDocument().getLength(), date + ": " + message + "\n", null);
				((JViewport) pane.getParent()).setViewPosition(new Point(0, pane.getHeight()));
			}
		}
		catch (BadLocationException e)
		{
			e.printStackTrace();
		}
	}

	@Override
	/**
	 * Runs thread which continuously receives messages
	 */
	public void run()
	{
		try
		{
			DomainInstance di = ckb.createInstance(instanceName);

			DomainClass dc = ckb.getDomainClass(className);
			di.setInstanceOf(dc);

			Hashtable<String, String> sensors = MidEmuApplication.getInstance().getSensors();

			Enumeration<String> keys = sensors.keys();
			while (keys.hasMoreElements())
			{
				String key = keys.nextElement();
				String sensorValueType = sensors.get(key);
				String sensorValue = MidEmuApplication.getInstance().readSensor(key);
				System.out.println("Setting " + sensorValueType + " on " + sensorValue);

				DomainProperty dp = ckb.getDomainProperty(sensorValueType);

				di.setDatatypePropertyValue(dp, Float.parseFloat(sensorValue));
			}

			connection = cam.getConnection();

			while (runCondition)
			{

				byte[] msg = connection.waitForMessage();
				if (msg != null)
					this.receive(msg);
			}

			connection.closeConnection();

		}
		catch (Exception ex)
		{
			System.out.println("Listener: START failure");
			ex.printStackTrace();
		}
	}

	/**
	 * Stops listening for messages
	 */
	public void stopLitening()
	{
		System.out.println("Listener: STOP attempt");
		runCondition = false;
		try
		{
			if (ckb != null)
				ckb.removeInstance(instanceName);
		}
		catch (ABoxException e)
		{
			e.printStackTrace();
		}
		finally
		{
			if (connection != null)
				connection.closeConnection();
		}

	}

	/**
	 * Terminates message receiver
	 */
	public void terminate()
	{
		stopLitening();
	}
}